package com.uh.microservice.core.util;

import org.apache.commons.lang.StringUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by liming on 2017/9/18.
 */
public class DateUtil {

    LogUtil log = new LogUtil(this.getClass());

    private static final String sdf0reg = "^\\d{2,4}\\-\\d{1,2}\\-\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}.\\d{1,}$";
    private static final String sdf1reg = "^\\d{2,4}\\-\\d{1,2}\\-\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}$";
    private static final String sdf2reg = "^\\d{2,4}\\-\\d{1,2}\\-\\d{1,2}$";
    private static final String sdf3reg = "^\\d{2,4}\\/\\d{1,2}\\/\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}$";
    private static final String sdf4reg = "^\\d{2,4}\\/\\d{1,2}\\/\\d{1,2}$";
    private static final String sdf5reg = "^\\d{8}$";
    private static final String sdf6reg = "^\\d{14}$";

    public static final String pattern1 = "yyyy-MM-dd";
    public static final String pattern2 = "yyyy-MM-dd HH:mm:ss";
    public static final String pattern3 = "yyyy/MM/dd";
    public static final String pattern4 = "yyyy/MM/dd HH:mm:ss";
    public static final String pattern5 = "yyMMddHHmmss";
    public static final String pattern6 = "HH:mm";
    public static final String pattern7 = "yyyyMMddHHmmss";
    public static final String pattern8 = "yyyyMMdd";

    public static final String yMD = "2000-01-01 ";

    public static Date parse(String str) {

        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy/MM/dd");
        SimpleDateFormat sdf5 = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sdf6 = new SimpleDateFormat("yyyyMMddHHmmss");

        Date date = null;
        Pattern p0 = Pattern.compile(sdf0reg);
        Matcher m0 = p0.matcher(str);
        Pattern p1 = Pattern.compile(sdf1reg);
        Matcher m1 = p1.matcher(str);
        Pattern p2 = Pattern.compile(sdf2reg);
        Matcher m2 = p2.matcher(str);
        Pattern p3 = Pattern.compile(sdf3reg);
        Matcher m3 = p3.matcher(str);
        Pattern p4 = Pattern.compile(sdf4reg);
        Matcher m4 = p4.matcher(str);
        Pattern p5 = Pattern.compile(sdf5reg);
        Matcher m5 = p5.matcher(str);
        Pattern p6 = Pattern.compile(sdf6reg);
        Matcher m6 = p6.matcher(str);


        try {
            if (m0.matches()) {
                date = sdf1.parse(str);
            } else if (m1.matches()) {
                date = sdf1.parse(str);
            } else if (m2.matches()) {
                date = sdf2.parse(str);
            } else if (m3.matches()) {
                date = sdf3.parse(str);
            } else if (m4.matches()) {
                date = sdf4.parse(str);
            } else if(m5.matches()){
                date = sdf5.parse(str);
            } else if(m6.matches()){
                date=sdf6.parse(str);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return date;
    }

    public static Date parse2Date(Object date){
        if(date instanceof String)
            return parse((String)date);
        else if(date instanceof Date)
            return (Date)date;
        return null;
    }
    public static Date parseString(String str, String pattern) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.parse(str);
    }

    public static String format(Date date) {
        return format(date, pattern2);
    }

    public static String format(String date){
        Date dt=parse(date);
        if(dt==null)
            return date;
        return format(dt);
    }
    
    public static String format(String date, String pattern){
        Date dt=parse(date);
        if(dt==null)
            return date;
        return format(dt,pattern);
    }

    public static String format(Date date, String pattern) {
        if (date == null) return "";
        if (StringUtils.isBlank(pattern)) pattern = pattern2;
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }

    public static Long getTime(Date date) {
        if (date == null) date = new Date();
        return date.getTime();
    }

    public static Long getSecondsTime(Date date){
        Long time=getTime(date);
        return new Long(time/1000);
    }


    /**
     * 日期加天数
     *
     * @param date 日期
     * @param day  天数
     * @return 日期
     */
    public static Date addDay(Date date, int day) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, day);
        return calendar.getTime();
    }

    /**
     * 日期减天数
     *
     * @param date 日期
     * @param day  天数
     * @return 日期
     */
    public static Date subDay(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) - day);
        return calendar.getTime();
    }

    /**
     * 日期加天数
     *
     * @param date 日期
     * @param day  天数
     * @return 日期
     */
    public static Date addDayByString(String date, int day) {

        Date d = parse(yMD + date);

        return addDay(d, day);
    }

    /**
     * 日期加分钟数
     *
     * @param date    日期
     * @param minutes 分钟
     * @return 日期
     */
    public static String addMinutes(String date, int minutes) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(parse(yMD + date));
        calendar.add(Calendar.MINUTE, minutes);
        return format(calendar.getTime(), "HH:mm:ss");
    }

    /**
     * 日期加分钟数
     *
     * @param fullDate 日期
     * @param minutes  分钟
     * @return 日期
     */
    public static String addMinutesFullDate(String fullDate, int minutes) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(parse(fullDate));
        calendar.add(Calendar.MINUTE, minutes);
        return format(calendar.getTime());
    }

    /**
     * 日期加分钟数
     *
     * @param fullDate 日期
     * @param minutes  分钟
     * @return 日期
     */
    public static Date addMinutesDate(Date fullDate, int minutes) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(fullDate);
        calendar.add(Calendar.MINUTE, minutes);
        return calendar.getTime();
    }
    /**
     * 日期减分钟数
     *
     * @param fullDate 日期
     * @param minute   分钟
     * @return 日期
     */
    public static Date subMinuteFullDate(Date fullDate, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(fullDate);
        calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - minute);
        return calendar.getTime();
    }

    /**
     * 日期减小时数
     *
     * @param fullDate 日期
     * @param hour     小时
     * @return 日期
     */
    public static Date subHourFullDate(Date fullDate, int hour) {
        return subMinuteFullDate(fullDate, hour * 60);
    }

    /**
     * 日期加小时数
     *
     * @param fullDate 日期
     * @param hour     小时
     * @return 日期
     */
    public static Date addHourFullDate(Date fullDate, int hour) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(fullDate);
        calendar.add(Calendar.HOUR_OF_DAY, hour);
        return calendar.getTime();
    }


    public static String calcParkTimes(Date begin, Date end) {
        if (begin == null || end == null) {
            return null;
        }
        long times = (end.getTime() - begin.getTime()) / 1000;
        StringBuilder sb = new StringBuilder();
        long days = times / (24 * 60 * 60);
        sb.append(days == 0 ? "" : days + "天");
        long hours = (times - (days * 24 * 60 * 60)) / (60 * 60);
        sb.append(hours == 0 ? "" : hours + "小时");
        long minutes = (times - (days * 24 * 60 * 60 + hours * 60 * 60)) / 60;
        sb.append(minutes == 0 ? "" : minutes + "分钟");
        return sb.toString();
    }

    /**
     * 得到两个日期之间相差的天数
     *
     * @param newDate 大的日期
     * @param oldDate 小的日期
     * @return newDate-oldDate相差的天数
     */
    public static int daysBetweenDates(Date newDate, Date oldDate) {
        int days = 0;
        Calendar calo = Calendar.getInstance();
        Calendar caln = Calendar.getInstance();
        calo.setTime(oldDate);
        caln.setTime(newDate);
        int oday = calo.get(Calendar.DAY_OF_YEAR);
        int nyear = caln.get(Calendar.YEAR);
        int oyear = calo.get(Calendar.YEAR);
        while (nyear > oyear) {
            calo.set(Calendar.MONTH, 11);
            calo.set(Calendar.DATE, 31);
            days = days + calo.get(Calendar.DAY_OF_YEAR);
            oyear = oyear + 1;
            calo.set(Calendar.YEAR, oyear);
        }
        int nday = caln.get(Calendar.DAY_OF_YEAR);
        days = days + nday - oday;

        return days;
    }

    /**
     * Returns a Date set to the first possible millisecond of the day, just
     * after midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getStartOfDay(Date day) {
        return getStartOfDay(day, Calendar.getInstance());
    }

    /**
     * Returns a Date set to the first possible millisecond of the day, just
     * after midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getStartOfDay(Date day, Calendar cal) {
        if (day == null)
            day = new Date();
        cal.setTime(day);
        cal.set(Calendar.HOUR_OF_DAY, cal.getMinimum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }

    /**
     * Returns a Date set to the last possible millisecond of the day, just
     * before midnight. If a null day is passed in, a new Date is created.
     * midnight (00m 00h 00s)
     */
    public static Date getEndOfDay(Date day) {
        return getEndOfDay(day, Calendar.getInstance());
    }

    public static Date getEndOfDay(Date day, Calendar cal) {
        if (day == null)
            day = new Date();
        cal.setTime(day);
        cal.set(Calendar.HOUR_OF_DAY, cal.getMaximum(Calendar.HOUR_OF_DAY));
        cal.set(Calendar.MINUTE, cal.getMaximum(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal.getMaximum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMaximum(Calendar.MILLISECOND));
        return cal.getTime();
    }

    /**
     * 返回当前小时数,最小分钟数
     * after midnight. If a null day is passed in, a new Date is created.
     */
    public static Date getHourFormat(Date day) {
        if (day == null)
            day = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(day);
        cal.set(Calendar.MINUTE, cal.getMinimum(Calendar.MINUTE));
        cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }

    /**
     * 返回当前分钟数,最小秒数
     * after midnight. If a null day is passed in, a new Date is created.
     */
    public static Date getMinuteFormat(Date day) {
        if (day == null)
            day = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(day);
        cal.set(Calendar.SECOND, cal.getMinimum(Calendar.SECOND));
        cal.set(Calendar.MILLISECOND, cal.getMinimum(Calendar.MILLISECOND));
        return cal.getTime();
    }
    /**
     * 当前星期几
     * 周一 - 周五 返回 0
     * 周六周日 返回 1
     *
     * @param date
     * @return
     */
    public static int getDayType(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int week = calendar.get(Calendar.DAY_OF_WEEK);//1:周日,2：周一,3:周二,4:周三,5:周四,6:周五:7:周六
        if (week == 1 || week == 7) {
            week = 1;
        } else {
            week = 0;
        }
        return week;
    }

    /**
     * false: a after b
     * true：a before b
     *
     * @param a
     * @param b
     * @return
     */
    public static long getSecondOfDate(String a, String b, boolean isNextDay) {
        if (StringUtils.isEmpty(a) || StringUtils.isEmpty(b)) {
            return 0;
        }
//        String yMD = "2000-01-01 ";
//        String yMDNextDay = "2000-01-02 ";
//        b = isNextDay ? yMDNextDay + b : yMD + b;
        return (parse(b).getTime() - parse(a).getTime()) / 1000;
    }

    /**
     * 是否在范围区间
     *
     * @param startTime 08:00
     * @param endTime   18:00
     * @param reqTime   请求时间
     * @return true or false
     */
    public static boolean isRange(String startTime, String endTime, Date reqTime) {
        SimpleDateFormat formatter = new SimpleDateFormat(pattern6);
        Date startDate = null;
        try {
            startDate = formatter.parse(startTime);
            Date endDate = formatter.parse(endTime);
            Date currentTime = new Date();
            if (reqTime != null) {
                currentTime = reqTime;
            }
            String dateString = formatter.format(currentTime);
            Date currDate = formatter.parse(dateString);
            if (startDate.getTime() >= endDate.getTime()) {
                endDate = addDay(endDate, 1);
            }
            if (startDate.getTime() > currDate.getTime()) {
                currDate = addDay(currDate, 1);
            }
            return isContain(currDate.getTime(), startDate.getTime(), endDate.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 时间是否包含
     *
     * @param currDate  当前时间
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return true or false
     */
    private static boolean isContain(long currDate, long startDate, long endDate) {
        if (currDate >= startDate && currDate < endDate) {
            return true;
        }
        return false;
    }

    /**
     * 获取两个时间相差秒数
     * (time1 - time2)/1000
     *
     * @param time1
     * @param time2
     * @return
     */
    public static long getTwoTimeDiffSecond(Date time1, Date time2) {
        long microsecond = time1.getTime() - time2.getTime();
        return microsecond / 1000;
    }

    /**
     * 获取当前系统时间
     *
     * @return
     */
    public static Timestamp getCurrentDateTime() {
        return new Timestamp(System.currentTimeMillis());
    }

    /**
     * timestamp 转 Date
     *
     * @param time
     * @return
     */
    public static Date timestamp2Date(Timestamp time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        return calendar.getTime();
    }

    /**
     * 获取日期年份
     *
     * @param date 日期
     * @return
     */
    public static String getYear(Date date) {
        return format(date).substring(0, 4);
    }

    /**
     * 功能描述：返回月
     *
     * @param date Date 日期
     * @return 返回月份
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 功能描述：返回日
     *
     * @param date Date 日期
     * @return 返回日份
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 功能描述：返回小
     *
     * @param date 日期
     * @return 返回小时
     */
    public static int getHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 功能描述：返回分
     *
     * @param date 日期
     * @return 返回分钟
     */
    public static int getMinute(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MINUTE);
    }

    /**
     * 返回秒钟
     *
     * @param date Date 日期
     * @return 返回秒钟
     */
    public static int getSecond(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.SECOND);
    }
    /**
     * 获取当前月前一个月的最后一天
     * @return
     */
    public static Date getLastMonthEndDay() {
    	Calendar calendar = Calendar.getInstance();
    	calendar.set(Calendar.DAY_OF_MONTH, 0);
    	return calendar.getTime();
    }
    
    /**
     * 获取两个日期间的所有日期
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> getDays(String startDate,String endDate){
    	List<String> days = new ArrayList<String>();
    	try {
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    		Date start = sdf.parse(startDate);
    		Date end = sdf.parse(endDate);
    		Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);

            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
            while (tempStart.before(tempEnd)) {
                days.add(sdf.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1);
            }
		} catch (Exception e) {
			e.printStackTrace();
		}
    	return days;
    }

    /**
     * 获取给定时间的一个整数时间
     * @return
     */
    public static String getIntTime(int tm,Date now){
        if(now ==null) now =new Date();
        SimpleDateFormat cf1 = new SimpleDateFormat("yyyy-MM-dd HH:");
        String dt1=cf1.format(now);

        SimpleDateFormat cfm = new SimpleDateFormat("mm");
        Integer nm=new Integer(cfm.format(now));
        Integer nm1=new Integer(new Double(Math.floor(nm/tm)*tm).intValue());
        String snm1=""+nm1; if(nm1<10)snm1="0"+nm1;

        String dt=dt1+snm1+":00";
        return dt;
    }

    public static int getMinutesFromDate(Date now){
        Date startDate = DateUtil.getStartOfDay(now);
        long ntime=getSecondsTime(now);
        long stime=getSecondsTime(startDate);
        Integer mins= new Integer(new Double((ntime-stime)/60).intValue());
        return mins.intValue();
    }
    
    public static String timestamp2String(Timestamp timestamp, String pattern) {
		if (timestamp == null) {
			throw new java.lang.IllegalArgumentException("timestamp null illegal");
		}
		if (pattern == null || pattern.equals("")) {
			pattern = pattern2;
		}
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(new Date(timestamp.getTime()));
	}

    /**
    * @Title: yesterday
    * @Description: 获取前一天日期，返回date类型
    * @param @return    参数
    * @return Date    返回类型
    * @throws
     */
	public static Date yesterday() {
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.DAY_OF_MONTH, -1);
		return cal.getTime();
	}
	
	/**
	    * @Title: getYesterday
	    * @Description: 获取前一天日期，返回String类型
	    * @param @return    参数
	    * @return String    返回类型
	    * @throws
	     */
		public static String getYesterday() {
			return format(yesterday(),pattern1);
		}

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
//            Date now = parse("2018-05-29 00:54:55");
//            System.out.println(DateUtil.getHour(now));
//            Date endDate=getStartOfDay(now);
//            int day=DateUtil.getDay(endDate);
//            System.out.println(day<10?'0'+String.valueOf(day):day);
//            Date startDate=DateUtil.subDay(endDate,7);
//            System.out.println(format(endDate));
//            System.out.println(format(startDate));
//            System.out.println(daysBetweenDates(endDate,startDate));

//            Date now = new Date();
//            Date statTime = DateUtil.subDay(now, 1);
//            Date startTime = DateUtil.getStartOfDay(statTime);
//            Date endTime = DateUtil.getEndOfDay(statTime);

            Date now =DateUtil.parse("2018-05-31 00:04:00");
            Date startDate = DateUtil.getStartOfDay(now);
            int minute = DateUtil.getMinute(now);
            Date endDate = DateUtil.getMinuteFormat(DateUtil.subMinuteFullDate(now, minute % 5));
            if(startDate.compareTo(endDate)==0){
                startDate=DateUtil.subDay(startDate,1);
            }
            System.out.println(format(startDate));
            System.out.println(format(endDate));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
